package com.billionsfinance.hessian.core;

import com.billionsfinance.hessian.annotation.EnableHessianServer;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.remoting.caucho.HessianServiceExporter;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.Set;

/**
 * @fileName: HessianBeanFactory.java
 * @author: WeiHui.Zhang
 * @date: 2016-10-10  16:09
 * @version: v1.0.0
 */
@Component
public class HessianServerBeanFactory implements ApplicationContextAware {

	private static final String defaultSuffix = ".htm";

	/**
	 * 访问前缀
	 */
	protected String prefix;

	/**
	 * 访问后缀
	 */
	protected String suffix;

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		ConfigurableApplicationContext context = (ConfigurableApplicationContext) applicationContext;
		Map<String, Object> beans = context.getBeanFactory().getBeansWithAnnotation(EnableHessianServer.class);
		Set<Map.Entry<String, Object>> entries = beans.entrySet();
		for (Map.Entry<String, Object> entry : entries) {
			String refBean = entry.getKey();
			Object value = entry.getValue();
			Class<?> clazz = value.getClass();
			Class<?> interfaces = clazz.getInterfaces()[0];
			registerBeanDefinition(context, refBean, interfaces.getName());
		}
	}

	/**
	 * 创建bean并且放入springBean工厂，取代xml的繁琐配置
	 * <p>
	 * 定义远程调用路由
	 * <bean name="/addService.htm" class="org.springframework.remoting.caucho.HessianServiceExporter">
	 * <property name="server" ref="addService"/>
	 * <property name="serviceInterface" value="com.john.spring.hessian.server.AddService"/>
	 * </bean>
	 * </p>
	 *
	 * @param context                   bean上下文
	 * @param hessianServiceImplRefBean serviceImpl--bean 的名称
	 * @param hessianServiceInterface   service的全类名
	 */
	private void registerBeanDefinition(ConfigurableApplicationContext context, String hessianServiceImplRefBean, String hessianServiceInterface) {
		// 通过BeanDefinitionBuilder创建bean定义
		BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(HessianServiceExporter.class);
		// 设置属性userAcctDAO,此属性引用已经定义的bean:userAcctDAO
		beanDefinitionBuilder.addPropertyReference("server", hessianServiceImplRefBean);
		beanDefinitionBuilder.addPropertyValue("serviceInterface", hessianServiceInterface);
		// 获取bean工厂并转换为DefaultListableBeanFactory
		DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory();
		// 注册bean
		StringBuilder beanName = new StringBuilder("/");
		if (!StringUtils.isEmpty(prefix)) {
			beanName.append(prefix);
		}
		beanName.append(hessianServiceImplRefBean);
		if (!StringUtils.isEmpty(suffix)) {
			beanName.append(suffix);
		} else {
			beanName.append(defaultSuffix);
		}
		beanFactory.registerBeanDefinition(beanName.toString(), beanDefinitionBuilder.getRawBeanDefinition());
	}

	public void setPrefix(String prefix) {
		this.prefix = prefix;
	}

	public void setSuffix(String suffix) {
		this.suffix = suffix;
	}
}